package com.wangshouyu.mp.micro.base.utils;

import com.google.common.net.HttpHeaders;
import com.google.common.net.MediaType;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.cert.X509Certificate;
import java.util.Map;

/**
 * @author 王守钰
 * @date 2020年08月16日 01:25
 * @description: http工具类
 */
public class HttpUtils {

    private HttpUtils(){
        
    }

    private static Logger log = LoggerFactory.getLogger(HttpUtils.class);

    /**
     * https
     */
    private static final String HTTPS = "https";

    /**
     * POST
     */
    private static final String POST = "POST";

    /**
     * GET
     */
    private static final String GET = "GET";

    /**
     * 连接超时
     */
    private static final Integer CONNECT_TIMEOUT = 3000;

    /**
     * 读取超时
     */
    private static final Integer READ_TIMEOUT = 3000;

    /**
     * utf-8
     */
    private static final String UTF8 = "UTF-8";

    protected static TrustManager myX509TrustManager = new X509TrustManager() {

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }

    };

    /**
     * 创建连接
     * @param requestUrl 请求地址
     * @param method 请求方法
     * @return 返回结果
     * @throws Exception
     */
    private static HttpURLConnection connection(String requestUrl, String method) throws Exception {
        // 定义请求
        URL url = new URL(requestUrl);
        // 打开和URL之间的连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 设置请求类型
        connection.setRequestMethod(method);
        // 设置连接超时
        connection.setConnectTimeout(CONNECT_TIMEOUT);
        // 设置读取超时
        connection.setReadTimeout(READ_TIMEOUT);

        if(requestUrl.indexOf(HTTPS)==0){
            SSLContext sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[]{myX509TrustManager}, null);
            ((HttpsURLConnection) connection).setSSLSocketFactory(sslcontext.getSocketFactory());
        }
        if(POST.equalsIgnoreCase(method)){
            // 发送POST请求必须设置如下两行
            connection.setDoOutput(true);
            connection.setDoInput(true);
        }
        return connection;
    }

    /**
     * get请求
     * @param url 地址
     * @return 响应结果
     * @throws Exception
     */
    public static String getData(String url) throws Exception {
        return getData(url, null);
    }

    /**
     * 获取数据
     * @param url 地址
     * @param headers 头
     * @return 响应结果
     * @throws Exception
     */
    private static String getData(String url, Map<String, String> headers) throws Exception {
        HttpURLConnection connection = null;
        BufferedReader in = null;
        //定义返回结果
        StringBuffer result = new StringBuffer();
        try{
            connection = connection(url, GET);
            if(null != headers){
                //循环遍历请求头
                for(String key : headers.keySet()){
                    connection.setRequestProperty(key, headers.get(key));
                }
            }
            // 建立实际的连接
            connection.connect();
            // 获取响应码
            int code = connection.getResponseCode();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            if(code < 200 || code >= 300){
                throw new RuntimeException("http response code:" + code + " errorMsg:" + result.toString());
            }
        }finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            if(connection != null){
                connection.disconnect();
            }
        }
        return result.toString();
    }

    /**
     * 发送流数据
     * @param requestUrl 请求地址
     * @param data 请求数据
     * @param headers 请求头
     * @param outputStream 输出流
     * @throws Exception
     */
    public static void postDataStream(String requestUrl, String data, Map<String, String> headers, OutputStream outputStream) throws Exception{
        HttpURLConnection connection = null;
        BufferedReader in = null;
        OutputStreamWriter out = null;
        InputStream inputStream = null;
        //定义返回结果
        StringBuffer result = new StringBuffer();
        try{
            connection = connection(requestUrl, POST);
            if(null != headers){
                //循环遍历请求头
                for(String key : headers.keySet()){
                    connection.setRequestProperty(key, headers.get(key));
                }
            }
            // 建立实际的连接
            connection.connect();
            // 获取URLConnection对象对应的输出流
            out = new OutputStreamWriter(connection.getOutputStream());
            out.write(data);
            out.flush();
            // 获取响应码
            int code = connection.getResponseCode();
            String type = connection.getHeaderField(HttpHeaders.CONTENT_TYPE);
            MediaType mediaType = MediaType.parse(type);
            if(mediaType.is(MediaType.ANY_IMAGE_TYPE)){
                //开始获取数据
                inputStream = connection.getInputStream();
                IOUtils.copy(inputStream, outputStream);
            }else if(mediaType.withCharset(Charset.forName(UTF8)).is(MediaType.JSON_UTF_8)){
                in = new BufferedReader(new InputStreamReader(connection.getInputStream(), UTF8));
                String line;
                while ((line = in.readLine()) != null) {
                    result.append(line);
                }
                log.error("生成输出流相应结果:{}", result.toString());
                throw new RuntimeException("生成输出流异常！");
            }else{
                throw new RuntimeException("生成输出流异常！");
            }
            if(code < 200 || code >= 300){
                throw new RuntimeException("http response code:" + code + " errorMsg:" + result.toString());
            }
        }finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
                if(connection != null){
                    connection.disconnect();
                }
                if(null != inputStream){
                    inputStream.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }

        }
    }

    /**
     * post数据
     * @param requestUrl 请求地址
     * @param data 请求数据
     * @param headers 请求头
     * @return 响应结果
     * @throws Exception
     */
    public static String postData(String requestUrl, String data, Map<String, String> headers, OutputStream outputStream) throws Exception{
        HttpURLConnection connection = null;
        BufferedReader in = null;
        OutputStreamWriter out = null;
        InputStream inputStream = null;
        //定义返回结果
        StringBuffer result = new StringBuffer();
        try{
            connection = connection(requestUrl, POST);
            if(null != headers){
                //循环遍历请求头
                for(String key : headers.keySet()){
                    connection.setRequestProperty(key, headers.get(key));
                }
            }
            // 建立实际的连接
            connection.connect();
            // 获取URLConnection对象对应的输出流
            out = new OutputStreamWriter(connection.getOutputStream());
            out.write(data);
            out.flush();
            // 获取响应码
            int code = connection.getResponseCode();


            String type = connection.getHeaderField(HttpHeaders.CONTENT_TYPE);
            if(MediaType.ANY_IMAGE_TYPE.is(MediaType.parse(type))){
                //开始获取数据
                inputStream = connection.getInputStream();
                IOUtils.copy(inputStream, outputStream);
            }else{
                in = new BufferedReader(new InputStreamReader(connection.getInputStream(), UTF8));
                String line;
                while ((line = in.readLine()) != null) {
                    result.append(line);
                }
            }

            if(code < 200 || code >= 300){
                throw new RuntimeException("http response code:" + code + " errorMsg:" + result.toString());
            }
        }finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            if(connection != null){
                connection.disconnect();
            }
        }
        return result.toString();
    }

}